package com.sparrow.common.uuid;

/**
 * 基于前缀 + 中缀 + 后缀 位运算LongId生成器
 */
public class LongIdGenerator {

    private final int preBits;
    private final int midBits;
    private final int suffixBits;
    private final long preLimitValue;
    private final long midLimitValue;
    private final long suffixLimitValue;


    public LongIdGenerator(int preBits, int midBits, int suffixBits) {
        if (preBits + midBits + suffixBits > 63) {
            throw new RuntimeException("位数不能超过63位");
        }
        this.preBits = preBits;
        this.midBits = midBits;
        this.suffixBits = suffixBits;

        preLimitValue = 1L << this.preBits;
        midLimitValue = 1L << this.midBits;
        suffixLimitValue = 1L << this.suffixBits;
    }

    public long getId(long pre, long mid, long suffix) {
        if (pre >= preLimitValue) {
            throw new RuntimeException("pre=" + pre + " more then maxvalue=" + preLimitValue);
        }
        if (mid >= midLimitValue) {
            throw new RuntimeException("mid=" + mid + " more then max value=" + midLimitValue);
        }
        if (suffix >= suffixLimitValue) {
            throw new RuntimeException("suffix=" + suffix + " more then max value=" + suffixLimitValue);
        }
        return (pre << (midBits + suffixBits)) | (mid << suffixBits) | suffix;
    }

    public long getPre(long id) {
        return id >> (midBits + suffixBits);
    }

    public long getMid(long id) {
        return (id >> suffixBits) & (midLimitValue - 1);
    }

    public long getSuffix(long id) {
        return id & (suffixLimitValue - 1);
    }

    public long getPreLimitValue() {
        return preLimitValue;
    }

    public long getMidLimitValue() {
        return midLimitValue;
    }

    public long getSuffixLimitValue() {
        return suffixLimitValue;
    }

    public static void main(String[] args) {
        int sid = 9999;
        int mid = 1;
        LongIdGenerator generator = new LongIdGenerator(10, 10, 14);
        long id1 = generator.getId(1023, mid, sid);
        System.out.println(id1);
        System.out.println("pre=" + generator.getPre(id1) + " preMaxValue=" + generator.preLimitValue + " mask=" + Long.toBinaryString(generator.preLimitValue - 1));
        System.out.println("mid=" + generator.getMid(id1) + " midMaxValue=" + generator.midLimitValue + " mask=" + Long.toBinaryString(generator.midLimitValue - 1));
        System.out.println("suffix=" + generator.getSuffix(id1));
        System.out.println("测试溢出");
        System.out.println(generator.getId(2048, mid, sid));
    }


}
